home *** CD-ROM | disk | FTP | other *** search
- #! /usr/local/bin/perl
- #
- # mxc - mail exchange (MX) checker
- #
- # invoke as:
- # mxc [-l msglevel]
- #
- # Copyright (C) 1992, 1993 PUUG - Grupo Portugues de Utilizadores
- # do Sistema UNIX
- # 1992, 1993 FCCN - Fundacao para o Desenvolvimento dos Meios
- # Nacionais de Calculo Cientifico
- #
- # Authors: Jorge Frazao de Oliveira <frazao@puug.pt>
- # Artur Romao <artur@dns.pt>
- #
- # This file is part of the DDT package, Version 2.0.
- #
- # Permission to use, copy, modify, and distribute this software and its
- # documentation for any purpose and without any fee is hereby granted,
- # provided that the above copyright notice appear in all copies. Neither
- # PUUG nor FCCN make any representations about the suitability of this
- # software for any purpose. It is provided "as is" without express or
- # implied warranty.
-
-
- # =()<push(@INC, "@<LIBDIR>@");>()=
- push(@INC, "/usr/local/lib/ddt/cmd");
-
- require "ddt.pl";
-
-
- # scan the standard input
- while (<STDIN>) {
- next if /^;/; # ignore commented lines
-
- chop; # strip record separator
- @Field = split(/\s+/, $_); # break the input line
-
- if (/^\$ORIGIN/) {
- $Origin = $Field[2]; # set to a different origin
-
- next;
- }
-
- if (/^[*\.\-0-9A-Za-z]+/) {
- $Name = &make_name($Field[1], $Origin);
- }
-
- if (/\tIN\tSOA\t/) {
- $Zone = $Name; # there's a new zone
- }
- elsif (/\tIN\tMX\t/) {
- # add a new MX RR to the list
- &new_MX($Zone, $Name, $Field[$#Field - 1], $Field[$#Field]);
- }
- elsif (/\tIN\tCNAME\t/) {
- $IsAlias{$Name} = 1; # this name is an alias
- }
- }
-
- foreach $Zone (keys %MX) {
- &show_zone($Zone);
- }
-
- exit 0;
-
-
- #
- # examine each of the $zone's MX's, and print the anomalies
- #
- sub show_zone {
- local($zone) = @_;
- local(@MXlist, $name, $rest, @NMX);
-
- print " ### ", &toupper($zone), " ###";
-
- @MXlist = split($LISTsep, $MX{$zone}); # this is the list of
- # the zone's MX's
-
- undef %NMX; # or else it survives between calls
-
- while ($mx = shift(@MXlist)) {
- # get the values of the RR...
- ($name, $rest) = split($ELEMsep2, $mx);
-
- # ... and put them in the "private" list for this name
- $NMX{$name} = &add_list($NMX{$name}, $rest);
- }
-
- foreach $name (keys %NMX) {
- &check_MX($name, $NMX{$name});
- }
-
- print "\n";
- }
-
-
- #
- # find out if there's anything wrong with the MX's for this $name
- #
- sub check_MX {
- local($name, $MXlist) = @_;
- local($mx, $str);
- local($weight, $pointer, *Xmx, *Amx, *MXarray);
- local($min_out, $s, $a, $e);
-
- $min_out = -1;
- @MXarray = split($LISTsep, $MXlist);
-
- # scan the records and get those pointing to external hosts
- foreach $mx ($[ .. $#MXarray) {
- ($weight, $pointer) = split($ELEMsep1, $MXarray[$mx]);
-
- if (!&is_below_cut($zone, $pointer)) {
- $str = sprintf("%s%-20s IN MX %4d %s",
- $Lpad[4], $name, $weight, $pointer);
-
- push(@Xmx, $str);
-
- # find the value for the most preferable external host
- if (($min_out > $weight) || ($min_out < 0)) {
- $min_out = $weight
- }
- }
- }
-
- if ($#Xmx && $Level >= 4) {
- ($s, $a) = $#Xmx > 1 ? ("s", "") : ("", " an");
-
- print "\n$Lpad[4]MX record$s pointing to$a external host$s";
-
- foreach $str ($[ .. $#Xmx) {
- print shift(@Xmx);
- }
- }
-
- # get the internal hosts which are less preferred than external ones
- if ($min_out >= 0 && $Level >= 4) {
- foreach $mx ($[ .. $#MXarray) {
- ($weight, $pointer) = split($ELEMsep1, $MXarray[$mx]);
-
- if (&is_below_cut($zone, $pointer) &&
- ($weight >= $min_out)) {
- $str = sprintf("%s%-20s IN MX %4d %s",
- $Lpad[4], $name,
- $weight, $pointer);
-
- push(@Xmx, $str);
- }
- }
-
- if ($#Xmx) {
- $s = $#Xmx > 1 ? "s" : "";
-
- print "\n$Lpad[4]MX record$s to local or delegated host$s after MX records to external hosts";
-
- foreach $str ($[ .. $#Xmx) {
- print shift(@Xmx);
- }
- }
- }
-
- if ($Level >= 2) {
- # get the MX RR's pointing to aliases
- foreach $mx ($[ .. $#MXarray) {
- ($weight, $pointer) = split($ELEMsep1, $MXarray[$mx]);
-
- if ($IsAlias{$pointer}) {
- $str = sprintf("%s%-20s IN MX %4d %s",
- $Lpad[2], $name, $weight, $pointer);
-
- push(@Amx, $str);
- }
- }
-
- if ($#Amx) {
- ($s, $e, $a) = $#Amx > 1 ? ("s", "es", "") :
- ("", "", " an");
-
- print "\n$Lpad[2]MX record$s pointing to$a alias$e";
-
- foreach $str ($[ .. $#Amx) {
- print shift(@Amx);
- }
- }
- }
- }
-
-
- #
- # add ($name, $weight, $pointer) tupple to the list of MX record for this $zone
- #
- sub new_MX {
- local($zone, $name, $weight, $pointer) = @_;
- local($tuple);
-
- $tuple = join($ELEMsep2, $name, join($ELEMsep1, $weight, $pointer));
-
- $MX{$zone} = &add_list($MX{$zone}, $tuple);
- }
-
-